﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;

namespace PIBV
{
    public class PID_BlindingList : PID_BaseClass
    {
        public const string TABLE_NAME_BLIND_PIDS = "PID_BlindingList_TABLE_NAME_BLIND_PIDS";
        public const string TABLE_NAME_CACHE = "PID_BlindingList_CACHE";

        const string SQL_BLIND_PIDS = " SELECT DISTINCT B_PID FROM BLINDING_LIST ";
        const string SQL_BLIND_TAGS = " SELECT DISTINCT B_TAG_NAME FROM BLINDING_LIST WHERE B_PID='{0}'";
        const string SQL_BLIND_TAG_UPD = " UPDATE BLINDING_LIST SET B_POSITION = '{0}',B_SIZE = '{1}' WHERE B_TAG_NAME='{2}' ";
        const string SQL_CACHE_CLEAR = " DELETE FROM CACHE ";
        const string SQL_GET_CACHE = " SELECT * FROM CACHE ";
        const string SQL_GET_TAGS_FOR_PID = " SELECT * FROM BLINDING_LIST WHERE B_PID = '{0}'";
        
        /// PROBLEM!   I am using LIKE operator to find PID, 
        const string SQL_GET_PDF_FILENAME_FROM_PID = " SELECT TOP 1 D_FILE_PDF FROM vw_DRAWING_REFBOOK WHERE PID LIKE '%{0}%' ";//" SELECT D_FILE_PDF FROM vw_DRAWING_REFBOOK WHERE PID = '{0}' ";
        const string SQL_GET_DGN_FILENAME_FROM_PID = " SELECT TOP 1 D_FILE_DGN FROM vw_DRAWING_REFBOOK WHERE PID LIKE '%{0}%' ";//" SELECT D_FILE_PDF FROM vw_DRAWING_REFBOOK WHERE PID = '{0}' ";

        const string SQL_GET_PID_FROM_PDF = " SELECT TOP 1 PID FROM vw_DRAWING_REFBOOK WHERE D_FILE_PDF LIKE '%{0}' ";//" SELECT D_FILE_PDF FROM vw_DRAWING_REFBOOK WHERE PID = '{0}' ";
        //ctor
        public PID_BlindingList()
        {
        }


        public string GetPIDFromPDF(string pdfFileName)
        {
            string result = "";
            object obj = ExecuteScalar(String.Format(SQL_GET_PID_FROM_PDF, pdfFileName));
            result = (obj != null) ? (Convert.ToString(obj)) : "";
            return result;
        }

        public DataTable GetBlindingTagsForPID(string pid)
        {
            DataTable tbl = null;
            string TableName = "BlindingTagsForPID";

            ds = ExecuteQueryInToDataSet(String.Format(SQL_GET_TAGS_FOR_PID,pid), ds, TableName, true);
            tbl = ds.Tables[TableName];

            return tbl;
        }

        /// <summary>
        /// Index blinding list.Find position on the drawing For each tag from blinding list. 
        /// </summary>
        /// <param name="pdfFolder">Folder whith PDF</param>
        /// <param name="pdf2Folder">Folder whith PDF converted from DGN</param>
        public void IndexBlindingTags(string pdfFolder,string pdf2Folder)
        {
            string TableNamePidsTags = "TableNamePidsTags";
            string pdfFileName = "";
            string dgnFileName = "";

            //fill in P&ID drawing list
            ds = ExecuteQueryInToDataSet(SQL_BLIND_PIDS, ds, TABLE_NAME_BLIND_PIDS, true);
            DataTable tbl = ds.Tables[TABLE_NAME_BLIND_PIDS];

            //iterate through P&ID
            foreach (DataRow r in tbl.Rows)
            {
                string pid = r[0].ToString();

                //fill in CACHE table from current P&ID
                object obj = ExecuteScalar(String.Format(SQL_GET_PDF_FILENAME_FROM_PID, pid));
                pdfFileName = obj != null ? Path.GetFileName(Convert.ToString(obj)) : "";

                obj = ExecuteScalar(String.Format(SQL_GET_DGN_FILENAME_FROM_PID, pid));
                dgnFileName = obj != null ? Path.GetFileName(Convert.ToString(obj)) : "";

                //clear table
                ExecuteQuery(SQL_CACHE_CLEAR);
                //index drawing

                if (String.IsNullOrEmpty(dgnFileName.Trim()))
                {
                    IndexDrawing(pdfFolder, pdfFileName);
                }
                else 
                {
                    //index DGN file
                    IndexDrawing(pdf2Folder, dgnFileName.ChangeExtensionToPDF());
                }
                

                //find all blinding tags from P&ID
                ds = ExecuteQueryInToDataSet(String.Format(SQL_BLIND_TAGS, pid), ds, TableNamePidsTags, true);
                ds = ExecuteQueryInToDataSet(SQL_GET_CACHE, ds, TABLE_NAME_CACHE, true);
                DataTable cacheTable = ds.Tables[TABLE_NAME_CACHE];
                DataTable tbl_tags = ds.Tables[TableNamePidsTags];
                foreach (DataRow rt in tbl_tags.Rows)
                {
                    string drawingSize = "";
                    //take tag
                    string tag_name = rt[0].ToString();
                    //try to find(map) tag in cache
                    string pos = GetTagPosition(tag_name, ref cacheTable,ref drawingSize);
                    //update database
                    UpdateBlindTag(tag_name, pos,drawingSize);
                }
            }
        }

        void UpdateBlindTag(string tagname, string position, string drawingSize)
        {
            Exception ex = ExecuteQuery(String.Format(SQL_BLIND_TAG_UPD, position, drawingSize, tagname));
        }

        string GetTagPosition(string tagName, ref DataTable cache, ref string drawingSize)
        {
            string result = "";
            bool IsMatched = true;
            int currNum = -1;
            
            bool bApplyNextRule = true;

            #region Finding rule 1
            // Rule:  this rule is appliable for the following tag's format: 11-LD-1123
            // Split by '-' and try to find this sequence in the database

            string[] arr = tagName.SplitSasTag();
            List<string> arr2 = new List<string>();
            

            string leftPart = "";
            string rightPart = "";
            for (int i = 0; i < arr.Length; i++)
            {
                if (i <= 1)
                {
                    leftPart += arr[i];
                }
                else
                {
                    rightPart += arr[i];
                }
            }

            //create new array for mapping
            arr = new string[] { leftPart, rightPart };
            int arr_lenght = arr.Length;

            for (int i = 0; i < cache.Rows.Count; i++)
            {
                currNum = i;
                arr2.Clear();

                for (int k = 0; k < arr_lenght; k++)
                {
                    if (i + k < cache.Rows.Count)
                    {
                        string s1 = cache.Rows[i + k]["CH_STR"].ToString();
                        arr2.Add(s1);
                    }
                }

                if (arr.Length == arr2.Count)
                {
                    IsMatched = true;
                    for (int i1 = 0; i1 < arr_lenght; i1++)//3
                    {
                        if (arr[i1].Trim().ToUpper() != arr2[i1].Trim().ToUpper())
                        {
                            IsMatched = false;
                        }
                    }
                }

                if (IsMatched)
                {
                    break;
                }
            }

            if (IsMatched && currNum > 0)
            {
                result = GetAverageCoords(cache.Rows[currNum]["CH_P1"].ToString(),
                                              cache.Rows[currNum]["CH_P2"].ToString(),
                                              cache.Rows[currNum]["CH_P3"].ToString(),
                                              cache.Rows[currNum]["CH_P4"].ToString(),
                                              cache.Rows[currNum + 1]["CH_P1"].ToString(),
                                              cache.Rows[currNum + 1]["CH_P2"].ToString(),
                                              cache.Rows[currNum + 1]["CH_P3"].ToString(),
                                              cache.Rows[currNum + 1]["CH_P4"].ToString()
                                              );

                drawingSize = cache.Rows[currNum]["CH_SIZE"].ToString();
                bApplyNextRule = false;
            }           

            #endregion
            
            #region Rule 2
            
            if (bApplyNextRule)
            {
                // Rule:  this rule is appliable for the following tag's format: 42PDT and 1123
                // Split by '-' and try to find this sequence in the database
                IsMatched = true;
                currNum = -1;

                arr = tagName.SplitSasTag();
                arr2.Clear();

                arr_lenght = arr.Length;

                for (int i = 0; i < cache.Rows.Count; i++)
                {
                    currNum = i;
                    arr2.Clear();

                    for (int k = 0; k < arr_lenght; k++)
                    {
                        if (i + k < cache.Rows.Count)
                        {
                            string s1 = cache.Rows[i + k]["CH_STR"].ToString();
                            arr2.Add(s1);
                        }
                    }

                    if (arr.Length == arr2.Count)
                    {
                        IsMatched = true;
                        for (int i1 = 0; i1 < arr_lenght; i1++)//3
                        {
                            if (arr[i1].Trim().ToUpper() != arr2[i1].Trim().ToUpper())
                            {
                                IsMatched = false;
                            }
                        }
                    }

                    if (IsMatched)
                    {
                        break;
                    }
                }

                if (IsMatched && currNum > 0)
                {
                    result = GetAverageCoords(cache.Rows[currNum]["CH_P1"].ToString(),
                                              cache.Rows[currNum]["CH_P2"].ToString(),
                                              cache.Rows[currNum]["CH_P3"].ToString(),
                                              cache.Rows[currNum]["CH_P4"].ToString(),
                                              cache.Rows[currNum + 1]["CH_P1"].ToString(),
                                              cache.Rows[currNum + 1]["CH_P2"].ToString(),
                                              cache.Rows[currNum + 1]["CH_P3"].ToString(),
                                              cache.Rows[currNum + 1]["CH_P4"].ToString(),
                                              cache.Rows[currNum + 2]["CH_P1"].ToString(),
                                              cache.Rows[currNum + 2]["CH_P2"].ToString(),
                                              cache.Rows[currNum + 2]["CH_P3"].ToString(),
                                              cache.Rows[currNum + 2]["CH_P4"].ToString()
                                              );
                    drawingSize = cache.Rows[currNum]["CH_SIZE"].ToString();
                    bApplyNextRule = false;


                    //result = cache.Rows[currNum]["CH_P1"].ToString();
                    //drawingSize = cache.Rows[currNum]["CH_SIZE"].ToString();
                    //bApplyNextRule = false;
                }
            }

            #endregion

            return result;
        }

        public void IndexDrawing(string pdfFolder,string pdfFileName)
        {
            AcrobatWrapper.FindText("", pdfFolder, pdfFileName, e => { WriteCacheRecord(e, pdfFileName); });
        }

        void WriteCacheRecord(PDFQuadArgs e, string pdfFileName)
        {
            ExecuteQuery(String.Format("INSERT INTO CACHE (CH_FILE_NAME,CH_STR,CH_P1,CH_P2,CH_P3,CH_P4,CH_SIZE) VALUES ('{0}','{1}','{2}','{3}','{4}','{5}','{6}')", 
                pdfFileName, 
                e.Text, 
                e.p1.X + "," + e.p1.Y,
                e.p2.X + "," + e.p2.Y,
                e.p3.X + "," + e.p3.Y,
                e.p4.X + "," + e.p4.Y,
                e.size.X + "," + e.size.Y
            ));
        }

        string GetAverageCoords(params string[] coords)
        {
            string result = "";

            int sumX = 0;
            int sumY = 0;
            foreach (string s in coords)
            {
                string[] pos = s.Split(',');
                sumX += Convert.ToInt32(pos[0]);
                sumY += Convert.ToInt32(pos[1]);
            }
            
            result = (int)sumX / coords.Length + "," + (int)sumY / coords.Length;

            return result;
        }


    }
}
